#include "tests_pch.h"

#include <maths/vector.h>

using namespace black;

#define F_EPSILON 0.001f

SUITE( vec3 )
{
	TEST( Constructor1 )
	{
		vec3 v( 1.f,  2.f, 3.f );
		CHECK_EQUAL( 1.f, v.x );
		CHECK_EQUAL( 2.f, v.y );
		CHECK_EQUAL( 3.f, v.z );
	}
	TEST( Constructor2 )
	{
		float fVals[] = { 1.f, 2.f, 3.f };
		vec3 v( fVals );
		CHECK_EQUAL( 1.f, v.x );
		CHECK_EQUAL( 2.f, v.y );
		CHECK_EQUAL( 3.f, v.z );
	}
	TEST( Constructor3 )
	{
		vec3 v( 2.f );
		CHECK_EQUAL( 2.f, v.x );
		CHECK_EQUAL( 2.f, v.y );
		CHECK_EQUAL( 2.f, v.z );
	}
	TEST( normalize )
	{
		vec3 v( 3.f, 0.f, 0.f );
		v.normalize();
		CHECK( vec3( 1.f, 0.f, 0.f ) == v );
	}
}

SUITE( vec3_128 )
{
	TEST( equal_float )
	{
		vec3_128 v( 1.f, 1.f, 1.f );

		CHECK( v == 1.f );
		CHECK( !( v == 2.f ) );
	}
	TEST( equal_vec3_128 )
	{
		vec3_128 v( 1.f, 0.f, 1.f );

		CHECK( v == vec3( 1.f, 0.f, 1.f ) );
		CHECK( v == vec3_128( 1.f, 0.f, 1.f ) );
		CHECK( !( v == vec3_128( 1.f, 1.f, 1.f ) ) );
	}
	TEST( notequal_float )
	{
		vec3_128 v( 1.f, 0.f, 1.f );
		vec3_128 v2( 1.f, 1.f, 1.f );

		CHECK( v != 1.f );
		CHECK( v2 != 2.f );
		CHECK( !( v2 != 1.f ) );
	}
	TEST( notequal_vec3_128 )
	{
		vec3_128 v( 1.f, 0.f, 1.f );

		CHECK( v != vec3( 0.f, 0.f, 1.f ) );
		CHECK( v != vec3_128( 0.f, 0.f, 1.f ) );
	}
	TEST( plusequal_vec3 )
	{
		vec3 v1( 1.f, 0.f, 1.f );
		vec3_128 v2( 2.2f, 1.f, 0.f );

		v2 += v1;
		CHECK( v2 == vec3( 3.2f, 1.f, 1.f ) );
		CHECK( v2 == vec3_128( 3.2f, 1.f, 1.f ) );
	}
	TEST( plusequal_vec3_128 )
	{
		vec3_128 v1( 1.f, 0.f, 1.f );
		vec3_128 v2( 2.2f, 1.f, 0.f );

		v2 += v1;
		CHECK( v2 == vec3( 3.2f, 1.f, 1.f ) );
		CHECK( v2 == vec3_128( 3.2f, 1.f, 1.f ) );
	}
	TEST( plusequal_float )
	{
		vec3_128 v( 1.2f, -0.3f, 1.1f );

		v += 1.f;
		CHECK( v == vec3( 2.2f, 0.7f, 2.1f ) );
		CHECK( v == vec3_128( 2.2f, 0.7f, 2.1f ) );
	}
	TEST( minusequal_vec3_128 )
	{
		vec3_128 v1( 1.f, 0.f, 1.f );
		vec3_128 v2( 2.2f, 1.f, 0.f );

		v2 -= v1;
		CHECK( v2 == vec3( 1.2f, 1.f, -1.f ) );
		CHECK( v2 == vec3_128( 1.2f, 1.f, -1.f ) );
	}
	TEST( minusequal_float )
	{
		vec3_128 v( 1.2f, -0.3f, 1.1f );

		v -= 1.f;
		CHECK( v.isEqual( vec3( 0.2f, -1.3f, 0.1f ), F_EPSILON ) );
		CHECK( v.isEqual( vec3_128( 0.2f, -1.3f, 0.1f ), F_EPSILON ) );
	}
	TEST( multiplyequal_float )
	{
		vec3_128 v( 1.2f, -0.3f, 1.1f );

		v *= 2.f;
		CHECK( v.isEqual( vec3( 2.4f, -0.6f, 2.2f ), F_EPSILON ) );
		CHECK( v.isEqual( vec3_128( 2.4f, -0.6f, 2.2f ), F_EPSILON ) );
	}
	TEST( divideequal_float )
	{
		vec3_128 v( 1.2f, -0.3f, 1.1f );

		v /= 2.f;
		CHECK( v.isEqual( vec3( 0.6f, -0.15f, 0.55f ), F_EPSILON ) );
		CHECK( v.isEqual( vec3_128( 0.6f, -0.15f, 0.55f ), F_EPSILON ) );
	}
	TEST( normalize )
	{
		vec3_128 v( 3.f, 0.f, 0.f );
		v.normalize();
		CHECK( v.isEqual( vec3_128( 1.f, 0.f, 0.f ), F_EPSILON ) );
	}
	TEST( length )
	{
		vec3_128 v1( -1.f, 0.f, 0.f );
		vec3_128 v2( 0.f, -1.f, 0.f );
		vec3_128 v3( 0.f, 0.f, -1.f );
		vec3_128 v4( 0.f, 0.f, 4.f );
		CHECK_EQUAL( 1.f, v1.length() );
		CHECK_EQUAL( 1.f, v2.length() );
		CHECK_EQUAL( 1.f, v3.length() );
		CHECK_EQUAL( 4.f, v4.length() );
	}
	TEST( squareLength )
	{
		vec3_128 v1( -1.f, 0.f, 0.f );
		vec3_128 v2( 0.f, -1.f, 0.f );
		vec3_128 v3( 0.f, 0.f, -1.f );
		vec3_128 v4( 0.f, 0.f, 4.f );
		CHECK_EQUAL( 1.f, v1.squaredLength() );
		CHECK_EQUAL( 1.f, v2.squaredLength() );
		CHECK_EQUAL( 1.f, v3.squaredLength() );
		CHECK_EQUAL( 16.f, v4.squaredLength() );
	}
}